/**
 * Copyright (c) 2005-2012 https://github.com/zhangkaitao
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package com.tyf.common.dao;

import com.tyf.common.domain.search.Searchable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.NoRepositoryBean;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 抽象DAO层基类 提供一些简便方法<br/>
 * 具体使用请参考测试用例：{@see com.tyf.common.repository.UserRepository}
 * <p/>
 * 想要使用该接口需要在spring配置文件的jpa:repositories中添加 factory-class=
 * "com.tyf.common.repository.support.SimpleBaseRepositoryFactoryBean"
 * <p/>
 * <p>
 * 泛型 ： M 表示实体类型；ID表示主键类型
 * <p>
 * User: Zhang Kaitao && liutao
 * <p>
 * Date: 13-1-12 下午4:46
 * <p>
 * Version: 1.0
 */
@NoRepositoryBean
public interface BaseDao<M, ID extends Serializable> extends JpaRepository<M, ID> {

    /**
     * 根据主键删除
     *
     * @param ids
     */
    void delete(ID[] ids);

    /*
     * (non-Javadoc)
     *
     * @see org.springframework.data.repository.CrudRepository#findAll()
     */
    List<M> findAll();

    /*
     * (non-Javadoc)
     *
     * @see
     * org.springframework.data.repository.PagingAndSortingRepository#findAll(
     * org.springframework.data.domain.Sort)
     */
    List<M> findAll(Sort sort);

    /**
     * Returns a {@link Page} of entities meeting the paging restriction
     * provided in the {@code Pageable} object.
     *
     * @param pageable
     * @return a page of entities
     */
    Page<M> findAll(Pageable pageable);

    /**
     * 根据条件查询所有 条件 + 分页 + 排序
     *
     * @param searchable
     * @return
     */
    Page<M> findAll(Searchable searchable);

    /**
     * 根据条件统计所有记录数
     *
     * @param searchable
     * @return
     */
    long count(Searchable searchable);
    
    /**======================eud-common===================**/
    /**
	 * 插入
	 */
	public M insert(M entity);
	
	/**
	 * 更新
	 */
	public M update(M entity);
	
	/**
	 * 根据实体选择性更新,属性为空的便不进行更新；会自动拼接分片条件
	 * @param entity 实体 
	 * @param updateBy 更新条件 多个条件以","分隔,如"billNo,divisionNo";
	 * 		还可带操作符,以"_"分隔,如"billNo,divisionNo_eq",与SearchOperator定义一致,不考虑支持in
	 * 		条件的值直接从entity获取;
	 * @return 当前更新行
	 */
	public int updateSelective(M entity, String updateBy);
	
	/**
	 * 根据实体id属性进行，支持联合主键属性;选择性更新,属性为空的便不进行更新；会自动拼接分片条件
	 * @param entity 实体 
	 * @param updateByOther 除主键属性外的其他属性;更新条件 多个条件以","分隔,如"billNo,divisionNo";
	 * 		还可带操作符,以"_"分隔,如"billNo,divisionNo_eq",与SearchOperator定义一致,不考虑支持in
	 * 		条件的值直接从entity获取;
	 * 
	 * @return 当前更新行
	 */
	public int updateByIdNames(M entity, String updateByOther);
	
	/**
	 * 根据参数条件进行更新，更新内容为传入的entity，不更新的属性则设为null；会自动拼接分片条件
	 * @param entity 更新内容的实体
	 * @param params key支持操作符,如"billNo_lt",默认为eq;
	 * 		下划线后的操作符与SearchOperator定义一致;
	 * 		支持in,value为List对象;
	 */
	public int updateByParams(M entity, Map<String, Object> params);

	/**
	 * 将实体的某个属性更新为当前值+1
	 * 应用于【打印次数-printCount】自动+1，【导出次数-outCount】自动+1
	 * @param params TODO
	 */
	public int updateForAutoIncrement(String propertyName, Map<String, Object> params);
	
	/**
	 * 根据参数条件进行删除；不会自动拼接分片条件
	 * @param params key支持操作符,如"billNo_lt",默认为eq;下划线后的操作符与SearchOperator定义一致;
	 * 			支持in,value为List对象
	 * @return TODO
	 */
	public int deleteByParams(Map<String, Object> params);
	
	/**
	 * 删除,根据实体id属性进行，支持联合主键属性；会自动拼接分片条件
	 * @param entity 实体 
	 * @param deleteByOther 除主键属性外的其他属性;更新条件 多个条件以","分隔,如"billNo,divisionNo";
	 * 		还可带操作符,以"_"分隔,如"billNo,divisionNo_eq",与SearchOperator定义一致,不考虑支持in
	 * 		条件的值直接从entity获取;
	 * 
	 * @return 
	 */
	public int deleteByIdNames(M entity, String deleteByOther);

	/**
	 * 将实体m脱离实体管理器
	 * @param m
	 */
	public void detach(M m);

	/**
	 * 获取实体的idNames
	 * @return
	 */
	public Iterable<String> getIdNames();

	/**
	 * 根据参数条件进行更新 以及 自定义的set部分
	 * @param entity
	 * @param params
	 * @param customSetQl  自定义的set部分的Ql，会自动拼接到updateByParams生成的Ql语句的set后面，例如：
	 *                    String customSetQl="printCount=printCount+1, creator=null"
	 * @return
	 */
	public int updateByParamsAndCustomSetQl(M entity,  Map<String, Object> params, String customSetQl);
}
